home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / shells / bashsrc.zoo / alias.c < prev    next >
C/C++ Source or Header  |  1991-06-05  |  7KB  |  280 lines

  1. /* alias.c -- Not a full alias, but just the kind that we use in the
  2.    shell.  Csh style alias is somewhere else. */
  3.  
  4. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  5.  
  6. This file is part of GNU Bash, the Bourne Again SHell.
  7.  
  8. Bash is free software; you can redistribute it and/or modify it under
  9. the terms of the GNU General Public License as published by the Free
  10. Software Foundation; either version 1, or (at your option) any later
  11. version.
  12.  
  13. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  14. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16. for more details.
  17.  
  18. You should have received a copy of the GNU General Public License along
  19. with Bash; see the file COPYING.  If not, write to the Free Software
  20. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  21.  
  22. #include "config.h"
  23. #include "general.h"
  24. #include "alias.h"
  25.  
  26. /* The number of slots to allocate when we need new slots. */
  27. #define alias_list_grow_amount 50
  28.  
  29. /* Non-zero means expand all words on the line.  Otherwise, expand
  30.    after first expansion if the expansion ends in a space. */
  31. int alias_expand_all = 0;
  32.  
  33. /* The list of aliases that we have. */
  34. ASSOC **aliases = (ASSOC **)NULL;
  35.  
  36. /* The number of slots in the above list. */
  37. static int aliases_size = 0;
  38.  
  39. /* The number of aliases that are in existence. */
  40. static int aliases_length = 0;
  41.  
  42. /* The last alias index found with find_alias (). */
  43. static int last_alias_index = 0;
  44.  
  45. /* Scan the list of aliases looking for one with NAME.  Return NULL
  46.    if the alias doesn't exist, else a pointer to the assoc. */
  47. ASSOC *
  48. find_alias (name)
  49.      char *name;
  50. {
  51.   register int i;
  52.  
  53.   for (i = 0; i < aliases_length; i++)
  54.     if (strcmp (name, aliases[i]->name) == 0)
  55.       return (aliases[last_alias_index = i]);
  56.  
  57.   return ((ASSOC *)NULL);
  58. }
  59.  
  60. /* Return the value of the alias for NAME, or NULL if there is none. */
  61. char *
  62. get_alias_value (name)
  63.      char *name;
  64. {
  65.   ASSOC *alias = find_alias (name);
  66.   if (alias)
  67.     return (alias->value);
  68.   else
  69.     return ((char *)NULL);
  70. }
  71.  
  72. /* Make a new alias from NAME and VALUE.  If NAME can be found,
  73.    then replace its value. */
  74. void
  75. add_alias (name, value)
  76.      char *name, *value;
  77. {
  78.   ASSOC *temp = find_alias (name);
  79.  
  80.   if (temp)
  81.     {
  82.       free (temp->value);
  83.       temp->value = savestring (value);
  84.     }
  85.   else
  86.     {
  87.       temp = (ASSOC *)xmalloc (sizeof (ASSOC));
  88.       temp->name = savestring (name);
  89.       temp->value = savestring (value);
  90.  
  91.       if ((aliases_length + 1) >= aliases_size)
  92.     {
  93.       if (!aliases)
  94.         aliases =
  95.           (ASSOC **)xmalloc ((aliases_size = alias_list_grow_amount)
  96.                  * sizeof (ASSOC *));
  97.       else
  98.         aliases =
  99.           (ASSOC **)xrealloc (aliases,
  100.                   (aliases_size += alias_list_grow_amount)
  101.                   * sizeof (ASSOC *));
  102.     }
  103.       aliases[aliases_length++] = temp;
  104.       aliases[aliases_length] = (ASSOC *)NULL;
  105.     }
  106. }
  107.  
  108. /* Remove the alias with name NAME from the alias list.  Returns
  109.    the index of the removed alias, or -1 if the alias didn't exist. */
  110. int
  111. remove_alias (name)
  112.      char *name;
  113. {
  114.   register int i;
  115.  
  116.   if (!find_alias (name))
  117.     return (-1);
  118.  
  119.   i = last_alias_index;
  120.   free (aliases[i]->name);
  121.   free (aliases[i]->value);
  122.   free (aliases[i]);
  123.  
  124.   for (; i < aliases_length; i++)
  125.     aliases[i] = aliases[i + 1];
  126.  
  127.   aliases_length--;
  128.   aliases[aliases_length] = (ASSOC *)NULL;
  129.  
  130.   return (last_alias_index);
  131. }
  132.  
  133. /* Delete all aliases. */
  134. delete_all_aliases ()
  135. {
  136.   register int i;
  137.  
  138.   for (i = 0; i < aliases_length; i++)
  139.     {
  140.       free (aliases[i]->name);
  141.       free (aliases[i]->value);
  142.       free (aliases[i]);
  143.       aliases[i] = (ASSOC *)NULL;
  144.     }
  145.  
  146.   aliases_length = 0;
  147. }
  148.  
  149. /* Return non-zero if CHARACTER is a member of the class of characters
  150.    that are self-delimiting in the shell. */
  151. self_delimiting (character)
  152.      int character;
  153. {
  154.   return (member (character, " \t\n\r;|&("));
  155. }
  156.  
  157. /* Return a new line, with any aliases substituted. */
  158. char *
  159. alias_expand (string)
  160.      char *string;
  161. {
  162.   int line_len = 1 + strlen (string);
  163.   char *line = (char *)xmalloc (line_len);
  164.   register int i, j, start, delimiter;
  165.   char *token = (char *)alloca (line_len);
  166.   int tl, real_start, in_command_position;
  167.   int expand_next = 1;
  168.   ASSOC *alias;
  169.  
  170.   line[0] = i = 0;
  171.  
  172.   /* Find the next word in line.  If it has an alias, substitute
  173.      the alias value.  If the value ends in ` ', then try again
  174.      with the next word.  Else, if there is no value, or if
  175.      the value does not end in space, we are done. */
  176.  
  177.  next_word:
  178.  
  179.   token[0] = 0;
  180.   /* Skip leading whitespace (or separator characters).
  181.      But save it in the output.  */
  182.   for (start = i; string[i]; i++)
  183.     {
  184.       if (whitespace (string[i]))
  185.     continue;
  186.  
  187.       if (self_delimiting (string[i]))
  188.     {
  189.       expand_next++;
  190.       continue;
  191.     }
  192.       break;
  193.     }
  194.  
  195.   if (start == i && string[i] == '\0')
  196.     return (line);
  197.  
  198.   j = strlen (line);
  199.   if (1 + j + (i - start) >= line_len)
  200.     line = (char *)xrealloc (line, line_len += (50 + (i - start)));
  201.   strncpy (line + j, string + start, i - start);
  202.   line[j + (i - start)] = '\0';
  203.  
  204.   real_start = i;
  205.  
  206.   in_command_position = (self_delimiting (string[i]) || expand_next);
  207.   expand_next = 0;
  208.  
  209.   /* From here to next separator character is a token. */
  210.   delimiter = 0;
  211.  
  212.   for (start = i; string[i]; i++)
  213.     {
  214.       switch (string[i])
  215.     {
  216.     case '\\':
  217.       if (string[i + 1])
  218.         {
  219.           i++;
  220.           continue;
  221.         }
  222.       break;
  223.  
  224.     case '"':
  225.     case '\'':
  226.       if (!delimiter)
  227.         delimiter = string[i];
  228.       else if (delimiter == string[i])
  229.         delimiter = 0;
  230.       break;
  231.     }
  232.  
  233.       if (!delimiter &&
  234.       (whitespace (string[i]) || self_delimiting (string[i])))
  235.     break;
  236.     }
  237.  
  238.   tl = strlen (token);
  239.   strncpy (token + tl, string + start, i - start);
  240.   token [tl += (i - start)] = '\0';
  241.  
  242.   /* See if this word has a substitution.  If it does, do the expansion,
  243.      but only if we are expanding all words, or if we are in a location
  244.      where an expansion is supposed to take place. */
  245.   alias = find_alias (token);
  246.  
  247.   if (alias && (in_command_position || alias_expand_all))
  248.     {
  249.       char *v = alias->value;
  250.       int l = strlen (v);
  251.       
  252.       /* +3 because we possibly add one more character below. */
  253.       if ((l + 3) > line_len - strlen (line))
  254.     line = (char *)xrealloc (line, line_len += (50 + l));
  255.  
  256.       strcat (line, v);
  257.  
  258.       if ((l && whitespace (v[l - 1])) || alias_expand_all)
  259.     {
  260.       if (l && whitespace (v[l -1]))
  261.         line[strlen (line) - 1] = '\0';
  262.       
  263.       expand_next = 1;
  264.     }
  265.     }
  266.   else
  267.     {
  268.       int ll = strlen (line), tl = i - real_start;
  269.       /* int tl = strlen (token); */
  270.  
  271.       if (ll + tl + 2 > line_len)
  272.     line = (char *)xrealloc (line, line_len += 50 + ll + tl);
  273.  
  274.       strncpy (line + ll, string + real_start, tl);
  275.       line[ll + tl] = '\0';
  276.       /* strcat (line, token); */
  277.     }
  278.   goto next_word;
  279. }
  280.